package com.zhongan.gateway.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.zhongan.gateway.common.constant.GwDeveloperApiConstant;
import com.zhongan.gateway.common.enums.GatewayErrorCodeEnum;
import com.zhongan.gateway.common.exception.GatewayException;
import com.zhongan.gateway.common.utils.SecurityUtil;
import com.zhongan.gateway.common.utils.TypeUtil;
import com.zhongan.gateway.dto.RequestBase;
import com.zhongan.gateway.dto.ResponseBase;
import com.zhongan.gateway.service.SecurityService;

@Component
public class SecurityServiceImpl implements SecurityService {

    private static final Logger logger = LoggerFactory.getLogger(SecurityServiceImpl.class);

    @Value("${gw.service.rsaPrivateKey}")
    private String              rsaPrivateKey;
    @Value("${gw.service.rsaPublicKey}")
    private String              rsaPublicKey;

    @Override
    public void encryptAndSign(ResponseBase responseBase, String publicKey, String type) throws GatewayException {
        logger.info("开始加密返回值...");
        try {
            //加密
            encrypt(responseBase, publicKey, type);
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            throw new GatewayException(GatewayErrorCodeEnum.UN_KNOWN.getCode(), "加密返回值失败");
        }
        logger.info("开始返回值签名...");
        try {
            sign(responseBase, type);
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            throw new GatewayException(GatewayErrorCodeEnum.UN_KNOWN.getCode(), "加签失败");
        }
        logger.info("返回值签名成功...");
    }

    @Override
    public JSONObject checkSignAndDecrypt(RequestBase requestBase, String publicKey, String type)
            throws GatewayException {
        logger.info("开始验签...");
        boolean signFlag = false;
        try {
            //验签
            signFlag = checkSign(requestBase, publicKey, type);
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
        }

        if (!signFlag) {
            throw new GatewayException(GatewayErrorCodeEnum.REQUEST_VERIFY_FAIL.getCode(), "签文有误,signValue:"
                    + requestBase.getSignValue());
        }
        logger.info("开始解密参数...");
        JSONObject obj = null;
        try {
            obj = decrypt(requestBase.getBizContent(), publicKey, type);
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            throw new GatewayException(GatewayErrorCodeEnum.REQUEST_DECRYPT_FAIL.getCode(), "解密失败");
        }
        logger.info("解密参数成功...");
        return obj;
    }

    private boolean checkSign(RequestBase requestBase, String publicKey, String type) throws Exception {
        String content = SecurityUtil.getSortedStr(requestBase);
        String sign = requestBase.getSignValue();
        boolean isSuccess = false;
        if (GwDeveloperApiConstant.ENCRYPT_TYPE_RSA.equals(type)) {
            isSuccess = SecurityUtil.rsaCheckSign(content, sign, publicKey);
        } else {
            isSuccess = SecurityUtil.md5CheckSign(content, sign);
        }
        return isSuccess;
    }

    private void sign(ResponseBase responseBase, String type) throws Exception {
        String content = SecurityUtil.getSortedStr(responseBase);

        String sign = "";
        if (GwDeveloperApiConstant.ENCRYPT_TYPE_RSA.equals(type)) {
            sign = SecurityUtil.rsaSign(content, rsaPrivateKey);
        } else {
            sign = SecurityUtil.md5Sign(content);
        }
        responseBase.setSignValue(sign);
    }

    private void encrypt(ResponseBase responseBase, String publicKey, String type) throws Exception {
        String content = TypeUtil.obj2Str(responseBase.getBizContent());

        if (GwDeveloperApiConstant.ENCRYPT_TYPE_RSA.equals(type)) {

            String result = SecurityUtil.rsaEncrypt(content, publicKey);
            responseBase.setBizContent(result);
        } else if (GwDeveloperApiConstant.ENCRYPT_TYPE_3DES.equals(type)) {

            String result = SecurityUtil.desEncrypt((String) content, publicKey);
            responseBase.setBizContent(result);
        }

    }

    /**
     * 验签
     * 
     * @param requestBase
     * @param publicKey
     * @param type
     * @return
     * @throws Exception
     */
    private JSONObject decrypt(Object content, String publicKey, String type) throws Exception {

        String decryptResult = "";
        JSONObject obj = null;
        if (GwDeveloperApiConstant.ENCRYPT_TYPE_RSA.equals(type)) {

            decryptResult = SecurityUtil.rsaDecrypt((String) content, rsaPrivateKey);
            obj = JSONObject.parseObject(decryptResult);
        } else if (GwDeveloperApiConstant.ENCRYPT_TYPE_3DES.equals(type)) {

            decryptResult = SecurityUtil.desDecrypt((String) content, publicKey);
            obj = JSONObject.parseObject(decryptResult);
        } else {
            if (content instanceof String) {
                obj = JSONObject.parseObject((String) content);
            } else {
                obj = (JSONObject) content;
            }
        }
        return obj;
    }
}
